home *** CD-ROM | disk | FTP | other *** search
/ Skunkware 5 / Skunkware 5.iso / src / X11 / xmbase-grok-1.2 / eval.c < prev    next >
C/C++ Source or Header  |  1995-06-25  |  6KB  |  265 lines

  1. /*
  2.  * evaluate an expression string, return result string or 0 if error
  3.  */
  4.  
  5. #include "config.h"
  6. #include <X11/Xos.h>
  7. #include <stdio.h>
  8. #include <stdlib.h>
  9. #include <Xm/Xm.h>
  10. #include "grok.h"
  11. #include "form.h"
  12. #include "proto.h"
  13. #include "y.tab.h"
  14.  
  15. extern int    yyparse(void);
  16. extern char    *progname;        /* argv[0] */
  17. extern Widget    toplevel;        /* top-level shell for error msg */
  18.  
  19. #if defined(bsdi) || defined(linux)
  20. extern
  21. #endif
  22. int        yylineno;        /* current line # being parsed */
  23. static char    *yyexpr;        /* first char read by lexer */
  24. static char    *yytext;        /* next char to be read by lexer */
  25. char        yyret[32768];        /* returned string (see parser.y) */
  26. static char    errormsg[200];        /* error message if any, or "" */
  27. static char    extramsg[100];        /* extra error message details */
  28. CARD        *yycard;        /* database for which to evaluate */
  29. char        *switch_name;        /* if switch statement was found, */
  30. char        *switch_expr;        /* .. name to switch to and expr */
  31.  
  32.  
  33.  
  34. /*
  35.  * callbacks from the yacc parser
  36.  */
  37.  
  38. int yywrap(void) { return(1); }
  39.  
  40. void yyerror(
  41.     char *msg)
  42. {
  43.     if (!*errormsg) {
  44.         sprintf(errormsg,
  45. "Problem with search expression\n%s:\n%.80s in column %d near '%.4s'\n%s",
  46.                 yyexpr, msg, yytext - yyexpr, yytext, extramsg);
  47.         fprintf(stderr, "%s: %s\n", progname, errormsg);
  48.     }
  49. }
  50.  
  51.  
  52. char *evaluate(
  53.     CARD        *card,
  54.     char        *exp)
  55. {
  56.     if (!exp)
  57.         return(0);
  58.     if (!*exp || *exp != '(' && *exp != '{' && *exp != '$')
  59.         return(exp);
  60.     *errormsg = 0;
  61.     *extramsg = 0;
  62.     yytext =
  63.     yyexpr = mystrdup(exp);
  64.     yycard = card;
  65.     *yyret = 0;
  66.  
  67.     (void)yyparse();
  68.  
  69.     free((void *)yyexpr);
  70.     if (*errormsg) {
  71.         create_error_popup(toplevel, 0, errormsg);
  72.         return(0);
  73.     }
  74.     return(yyret);
  75. }
  76.  
  77. BOOL evalbool(
  78.     CARD        *card,
  79.     char        *exp)
  80. {
  81.     if (!(exp = evaluate(card, exp)))
  82.         return(FALSE);
  83.     while (*exp == ' ' || *exp == '\t')
  84.         exp++;
  85.     return(*exp && *exp != '0' && *exp != 'f' && *exp != 'F');
  86. }
  87.  
  88.  
  89. #define ISDIGIT(c) ((c)>='0' && (c)<='9')
  90. #define ISSYM_B(c) ((c)>='a' && (c)<='z' || (c)>='A' && (c)<='Z')
  91. #define ISSYM(c)   ((c)>='0' && (c)<='9' || (c)=='_' || ISSYM_B(c))
  92.  
  93. static char *pair_l  = "=!<><>&|+/-*%|&.+-";
  94. static char *pair_r  = "====<>&|========+-";
  95. static short value[] = { EQ, NEQ, LE, GE, SHL, SHR, AND, OR,
  96.              PLA, DVA, MIA, MUA, MOA, ORA, ANA, APP, INC, DEC };
  97.  
  98. static struct symtab { char *name; int token; } symtab[] = {
  99.             { "this",    THIS    },
  100.             { "last",    LAST    },
  101.             { "avg",    AVG    },
  102.             { "dev",    DEV    },
  103.             { "var",    VAR    },
  104.             { "min",    AMIN    },
  105.             { "max",    AMAX    },
  106.             { "sum",    SUM    },
  107.             { "abs",    ABS    },
  108.             { "qavg",    QAVG    },
  109.             { "qdev",    QDEV    },
  110.             { "qmin",    QMIN    },
  111.             { "qmax",    QMAX    },
  112.             { "qsum",    QSUM    },
  113.             { "savg",    SAVG    },
  114.             { "sdev",    SDEV    },
  115.             { "smin",    SMIN    },
  116.             { "smax",    SMAX    },
  117.             { "ssum",    SSUM    },
  118.             { "int",    INT    },
  119.             { "bound",    BOUND    },
  120.             { "len",    LEN    },
  121.             { "chop",    CHOP    },
  122.             { "substr",    SUBSTR    },
  123.             { "in",        IN    },
  124.             { "sqrt",    SQRT    },
  125.             { "exp",    EXP    },
  126.             { "log",    LOG    },
  127.             { "ln",        LN    },
  128.             { "pow",    POW    },
  129.             { "random",    RANDOM    },
  130.             { "sin",    SIN    },
  131.             { "cos",    COS    },
  132.             { "tan",    TAN    },
  133.             { "asin",    ASIN    },
  134.             { "acos",    ACOS    },
  135.             { "atan",    ATAN    },
  136.             { "atan2",    ATAN2    },
  137.             { "date",    DATE    },
  138.             { "time",    TIME    },
  139.             { "duration",    DURATION},
  140.             { "year",    YEAR    },
  141.             { "month",    MONTH    },
  142.             { "day",    DAY    },
  143.             { "hour",    HOUR    },
  144.             { "minute",    MINUTE    },
  145.             { "second",    SECOND    },
  146.             { "leap",    LEAP    },
  147.             { "julian",    JULIAN    },
  148.             { "host",    HOST    },
  149.             { "user",    USER    },
  150.             { "uid",    UID    },
  151.             { "gid",    GID    },
  152.             { "access",    ACCESS    },
  153.             { "section",    SECTION_},
  154.             { "dbase",    DBASE_    },
  155.             { "form",    FORM_    },
  156.             { "prevform",    PREVFORM},
  157.             { "switch",    SWITCH    },
  158.             { "system",    SYSTEM    },
  159.             { "printf",    PRINTF    },
  160.             { "beep",    BEEP    },
  161.             { "error",    ERROR    },
  162.             { 0,        0    }
  163. };
  164.  
  165.  
  166. /*
  167.  * return next token and its value, called by parser
  168.  */
  169.  
  170. int yylex(void)
  171. #if 0 /* debug lexer */
  172. {
  173.     int Xyylex(void);
  174.     int t = Xyylex();
  175.     if (t > 31 && t < 127)
  176.         printf("== '%c'\n", t);
  177.     else switch(t) {
  178.       case 0:    printf("== EOF\n");                break;
  179.       case NUMBER:    printf("== number %g\n", yylval.dval);        break;
  180.       case STRING:    printf("== string \"%s\"\n", yylval.sval);    break;
  181.       case SYMBOL:    printf("== symbol \"%s\"\n", yylval.sval);    break;
  182.       case VAR:    printf("== var %c\n", yylval.ival + 'a');    break;
  183.       case FIELD:    printf("== field %d\n", yylval.ival);        break;
  184.       default:    printf("== token %d\n", t);            break;
  185.     }
  186.     return(t);
  187. }
  188. int Xyylex(void)
  189. #endif
  190. {
  191.     int        i;
  192.     register struct symtab *sym;
  193.     register ITEM    **item;
  194.     char        msg[100], token[100], *tp=token;
  195.  
  196.     while (*yytext == ' ' || *yytext == '\t')        /* blanks */
  197.         yytext++;
  198.     if (!*yytext)                        /* eof */
  199.         return(0);
  200.                                 /* number */
  201.     if (ISDIGIT(*yytext) || *yytext == '.' && ISDIGIT(yytext[1])) {
  202.         char *ptr;
  203.         yylval.dval = strtod(yytext, &ptr);
  204.         yytext = ptr;
  205.         return(NUMBER);
  206.     }
  207.                                 /* string */
  208.     if (*yytext == '\'' || *yytext == '"') {
  209.         char quote = *yytext++;
  210.         char *begin = yytext;
  211.         while (*yytext && *yytext != quote)
  212.             if (*yytext++ == '\\' && *yytext)
  213.                 yytext++;
  214.         if (!*yytext)
  215.             return(0); /* unterminated */
  216.         *yytext = 0;
  217.         yylval.sval = mystrdup(begin);
  218.         *yytext++ = quote;
  219.         return(STRING);
  220.     }
  221.     if (*yytext>='a'&&*yytext<='z'&&!ISSYM(yytext[1])) {    /* variable */
  222.         yylval.ival = *yytext++ - 'a';
  223.         return(VAR);
  224.     }
  225.     if (*yytext == '_') {                    /* field */
  226.         yytext++;
  227.         while (ISSYM(*yytext))
  228.             *tp++ = *yytext++;
  229.         *tp = 0;
  230.         if (yycard && yycard->form) {
  231.             item = yycard->form->items;
  232.             if (ISDIGIT(*token)) {            /* ...numeric*/
  233.                 yylval.ival = atoi(token);
  234.                 return(FIELD);
  235.             } else                    /* ...name */
  236.                 for (i=yycard->form->nitems-1; i >= 0; i--)
  237.                     if (!strcmp(item[i]->name, token)) {
  238.                         yylval.ival = yycard->form->
  239.                                   items[i]->column;
  240.                         return(FIELD);
  241.                     }
  242.         }
  243.         sprintf(msg, "Illegal field \"_%s\"", token);
  244.         yyerror(msg);
  245.         return(EOF);
  246.     }
  247.     if (ISSYM_B(*yytext)) {                    /* symbol */
  248.         while (ISSYM(*yytext))
  249.             *tp++ = *yytext++;
  250.         *tp = 0;
  251.         for (sym=symtab; sym->name; sym++)        /* ...token? */
  252.             if (!strcmp(sym->name, token))
  253.                 return(sym->token);
  254.         yylval.sval = mystrdup(token);            /* ...symbol */
  255.         return(SYMBOL);
  256.     }
  257.     for (i=0; pair_l[i]; i++)                /* char pair */
  258.         if (*yytext == pair_l[i] && yytext[1] == pair_r[i]) {
  259.             yytext += 2;
  260.             return(value[i]);
  261.         }
  262.  
  263.     return(*yytext++);                    /* char */
  264. }
  265.